package com.neu.cpsp.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.neu.cpsp.pojo.*;
import com.neu.cpsp.service.DepartmentService;
import com.neu.cpsp.service.EmployeeService;
import com.neu.cpsp.util.JWTUtils;
import com.neu.cpsp.util.result.Result;
import com.neu.cpsp.util.result.ResultGenerator;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author neu.xiangwenjuan
 * @date 2022/3/9 16:02
 */
@CrossOrigin
@RestController
@RequestMapping("/employee")
public class EmployeeController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private EmployeeService employeeService;

    @Autowired
    private DepartmentService departmentService;

    /**
     * 分页显示，一次几条数据。
     * @param pageNum
     * @param pageSize
     * @param request
     * @return
     */
    @ApiOperation("获得所有人员信息")
    @RequestMapping(value = "/getAllEmployeeInfo", method = RequestMethod.GET)
    @ResponseBody
    private Result getAllEmployeeInfo(@RequestParam(defaultValue = "1") Integer pageNum,
                                      @RequestParam(defaultValue = "10") Integer pageSize,
                                      HttpServletRequest request) {
        // 调用这个方法一次，数据库中就有数据了，可以把这个方法注释掉，防止多次向数据库插入数据。
        //insertToTable();
        // 根据token得到用户信息，从而确定用户角色

        String token = request.getHeader("token");
        DecodedJWT verify = JWTUtils.verify(token);

        // 得到用户的工号，确认部门，根据角色判断用户权限。
        String role = verify.getClaim("role").asString();
        String jobNumber = verify.getClaim("jobNumber").asString();
        EmployeeEntity employee = employeeService.selectByJobNumber(jobNumber);

        PageHelper.startPage(pageNum,pageSize);

        List<EmployeeEntity> employeeList = new ArrayList<>();
        if (role.equals("admin") || role.equals("leader") || role.equals("supervision")) {
            employeeList = employeeService.selectAll();
        }else if (role.equals("department")){
            employeeList = employeeService.selectEmployeesByDepartment(employee.getDepartment().getDepartmentId());
        }
        for (EmployeeEntity employees:employeeList) {
            employees.setAge(tranCardToAge(employees.getIdCard()));
        }

        PageInfo pageInfo = PageInfo.of(employeeList);

        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @ApiOperation("修改人员信息——班组和是否为生产岗位")
    @RequestMapping(value = "/updateEmployeeInfo", method = RequestMethod.POST)
    @ResponseBody
    private Result updateEmployeeInfo(Employee employee) {
        int count = employeeService.updateByPrimaryKeySelective(employee);
        if (count > 0) {
            return ResultGenerator.genSuccessResult("修改成功！");
        }else {
            return ResultGenerator.genSuccessResult("修改失败！");
        }
    }

    @ApiOperation("根据参数选择性筛选人员信息")
    @RequestMapping(value = "getInfoSelective",method = RequestMethod.GET)
    @ResponseBody
    private Result getInfoSelective(
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize,
            String department,String teamGroup, Integer isDirectProducer, String name) {
        PageHelper.startPage(pageNum, pageSize);
        List<EmployeeEntity> list = employeeService.selectInfoSelective(department, teamGroup, isDirectProducer, name);
        for (EmployeeEntity employees:list) {
            employees.setAge(tranCardToAge(employees.getIdCard()));
        }
        PageInfo pageInfo = PageInfo.of(list);
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @ApiOperation("根据id得到员工信息")
    @RequestMapping(value = "getEmployeeById",method = RequestMethod.GET)
    @ResponseBody
    private Result getEmployeeById(Integer id) {
        EmployeeEntity employee = employeeService.getById(id);
        employee.setAge(tranCardToAge(employee.getIdCard()));
        if (employee != null) {
            return ResultGenerator.genSuccessResult(employee);
        }else {
            return ResultGenerator.genFailResult("id无效！");
        }
    }

    @ApiOperation("根据姓名得到员工信息")
    @RequestMapping(value = "getEmployeeByName",method = RequestMethod.GET)
    @ResponseBody
    private Result getEmployeeByName(String name) {
        List<EmployeeEntity> list = employeeService.selectByName(name);
        for (EmployeeEntity employees:list) {
            employees.setAge(tranCardToAge(employees.getIdCard()));
        }
        return ResultGenerator.genSuccessResult(list);
    }

    @ApiOperation("根据工号得到员工信息")
    @RequestMapping(value = "getEmployeeByJobNumber",method = RequestMethod.GET)
    @ResponseBody
    private Result getEmployeeByJobNumber(String jobNumber) {
        EmployeeEntity employee = employeeService.selectByJobNumber(jobNumber);
        employee.setAge(tranCardToAge(employee.getIdCard()));
        return ResultGenerator.genSuccessResult(employee);
    }

    @ApiOperation("根据部门获得人员信息")
    @RequestMapping(value = "getInfoByDepartment",method = RequestMethod.GET)
    @ResponseBody
    private Result getInfoByDepartment(@RequestParam(required = true) String department) {
        List<EmployeeEntity> list = employeeService.selectInfoSelective(department,null,null,null);
        for (EmployeeEntity employees:list) {
            employees.setAge(tranCardToAge(employees.getIdCard()));
        }
        return ResultGenerator.genSuccessResult(list);
    }

    @ApiOperation("根据请求获得登录员工的角色")
    @RequestMapping(value = "getLoginInfo",method = RequestMethod.GET)
    @ResponseBody
    private Result getLoginInfo(HttpServletRequest request) {
        String token = request.getHeader("token");
        DecodedJWT verify = JWTUtils.verify(token);

        // 得到用户的工号，确认部门，根据角色判断用户权限。
        String role = verify.getClaim("role").asString();
        // 返回角色信息
        return ResultGenerator.genSuccessResult(role);
    }

    @ApiOperation("根据请求获得登录员工的基本信息")
    @RequestMapping(value = "getLoginEmployeeInfo",method = RequestMethod.GET)
    @ResponseBody
    private Result getLoginEmployeeInfo(HttpServletRequest request) {
        String token = request.getHeader("token");
        DecodedJWT verify = JWTUtils.verify(token);
        String jobNumber = verify.getClaim("jobNumber").asString();
        EmployeeEntity employee = employeeService.selectByJobNumber(jobNumber);
        employee.setAge(tranCardToAge(employee.getIdCard()));
        return ResultGenerator.genSuccessResult(employee);
    }

    private int tranCardToAge(String idCard) {
        int age = 0;
        Calendar cal = Calendar.getInstance();
        int yearNow = cal.get(Calendar.YEAR);
        int monthNow = cal.get(Calendar.MONTH)+1;
        int dayNow = cal.get(Calendar.DATE);

        int year = Integer.valueOf(idCard.substring(6, 10));
        int month = Integer.valueOf(idCard.substring(10,12));
        int day = Integer.valueOf(idCard.substring(12,14));

        if ((month < monthNow) || (month == monthNow && day<= dayNow) ){
            age = yearNow - year;
        }else {
            age = yearNow - year-1;
        }
        return age;
    }

    /**
     * 插入部门信息
     * @return
     */
    private boolean insertDepartmentToTable()
    {
        // 得到所有部门信息
        Object object = testPost("department", new DepartmentFromCompany());
        String json = JSON.toJSONString(object);
        DepartmentFromCompany departmentFromCompany = JSONObject.parseObject(json,DepartmentFromCompany.class);
        DepartmentFromCompanyData[] departmentDatas = departmentFromCompany.getData();

        boolean res = true;
        for (DepartmentFromCompanyData departmentData : departmentDatas)
        {
            String  departmentId   = departmentData.getId(),
                    departmentName = departmentData.getDWMC();

            Department insertDepartment = new Department(departmentId, departmentName);

            // 插入 department
            res = res && departmentService.insert(insertDepartment);
        }

        return res;
    }

    /**
     * 插入员工数据
     * @return
     */
    private boolean insertEmployeeToTable()
    {
        // 得到所有用户信息
        Object object = testPost("user",new EmployeeFromCompany());
        String json = JSON.toJSONString(object);
        EmployeeFromCompany employeeFromCompany = JSONObject.parseObject(json, EmployeeFromCompany.class);
        EmployeeFromCompanyData[] employeeDatas = employeeFromCompany.getData();

        boolean dateFlag    = getPassDaySeason(new Date()) < 45,
                res         = true;

        for (EmployeeFromCompanyData employeeData : employeeDatas)
        {

            String  name            = employeeData.getName(),
                    idCard          = employeeData.getIdcard(),
                    jobNumber       = employeeData.getId(),
                    positionType    = employeeData.getPosition(),
                    departmentId    = employeeData.getDwh_id();

            Boolean is45Days = dateFlag || getCountBetweenTwoDates(employeeData.getStart(), new Date()) < 45;

            Employee insertEmployee = new Employee(name, idCard, jobNumber, is45Days, positionType, departmentId);

            res = res && employeeService.submitAllInfo(insertEmployee);
        }

        return res;
    }

    /**
     * 工具类，如果员工表里面没有数据，就插入，如果有，就查找部门有没有变化。
     * 每天凌晨运行一次。
     */
    @Scheduled(cron = "0 0 0 * * ?")
    private void updateEmployeeInfo() {
        List<EmployeeEntity> employees = employeeService.selectAll();
        if (employees.size() == 0) {
            insertEmployeeToTable();
        }else {
            // 通过甲方提供的接口获得员工信息。
            Object object = testPost("user",new EmployeeFromCompany());
            String json = JSON.toJSONString(object);
            EmployeeFromCompany employeeFromCompany = JSONObject.parseObject(json, EmployeeFromCompany.class);
            EmployeeFromCompanyData[] employeeDatas = employeeFromCompany.getData();
            for (EmployeeFromCompanyData employee : employeeDatas) {
                boolean flag = false;
                for (EmployeeEntity employeeEntity : employees) {
                    if (employee.getIdcard().equals(employeeEntity.getIdCard())) {
                        flag = true;
                        if (!employeeEntity.getDepartment().getDepartmentId().equals(employee.getDwh_id())) {
                            Employee employeeInfo = new Employee();
                            employeeInfo.setId(employeeEntity.getId());
                            employeeInfo.setDepartmentId(employee.getDwh_id());
                            int tag = employeeService.updateByPrimaryKeySelective(employeeInfo);
                            if (tag > 0) {
                                System.out.println("更新员工表成功！");
                            }else  {
                                System.out.println("更新员工表失败！");
                            }
                        }
                    }
                }
                if (!flag) {// 说明该员工在人事系统中存在，但在绩效系统中不存在。 需要插入到系统中。
                    boolean dateFlag    = getPassDaySeason(new Date()) < 45;
                    String  name            = employee.getName(),
                            idCard          = employee.getIdcard(),
                            jobNumber       = employee.getId(),
                            positionType    = employee.getPosition(),
                            departmentId    = employee.getDwh_id();

                    Boolean is45Days = dateFlag || getCountBetweenTwoDates(employee.getStart(), new Date()) < 45;

                    Employee insertEmployee = new Employee(name, idCard, jobNumber, is45Days, positionType, departmentId);
                    boolean tag = employeeService.submitAllInfo(insertEmployee);
                    if (tag) {
                        System.out.println("插入新员工成功！");
                    }else {
                        System.out.println("插入新员工成功！");
                    }
                }
            }
        }
    }

    // 得到两个日期之间的差值
    private int getCountBetweenTwoDates(String start, Date data) {
        DateFormat dft = new SimpleDateFormat("yyyy-MM-dd");
        int day = 0;
        try{
            Date star = dft.parse(start);
            Long startTime = star.getTime();
            Long endTime = data.getTime();
            Long num = endTime - startTime;
            day =(int)(num/24/60/60/1000);
        }catch (ParseException e) {
            e.printStackTrace();
        }
        return day;
    }
    // 下面四个方法用来获得当前季度已经度过多少天
    private int getPassDaySeason(Date date) {
        int day = 0;
        Date[] seasonDates = getSeasonDate(date);

        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int month = c.get(Calendar.MONTH);

        if (month == Calendar.JANUARY || month == Calendar.APRIL || month == Calendar.JULY || month == Calendar.OCTOBER ) {
            day = getPassDayOfMonth(seasonDates[0]);
        }else if (month == Calendar.FEBRUARY || month == Calendar.MAY || month == Calendar.AUGUST || month == Calendar.NOVEMBER ) {
            day = getPassMaxDayOfMonth(seasonDates[0]) + getPassDayOfMonth(seasonDates[1]);
        }else if (month == Calendar.MARCH || month == Calendar.JUNE || month == Calendar.SEPTEMBER || month == Calendar.DECEMBER ) {
            day = getPassMaxDayOfMonth(seasonDates[0]) + getPassMaxDayOfMonth(seasonDates[1]) + getPassDayOfMonth(seasonDates[2]);
        }
        return day;
    }
    private int getPassDayOfMonth(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.DAY_OF_MONTH);
    }
    private int getPassMaxDayOfMonth(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.getActualMaximum(Calendar.DAY_OF_MONTH);
    }
    private Date[] getSeasonDate(Date date) {
        Date[] season = new Date[3];

        Calendar c = Calendar.getInstance();
        c.setTime(date);

        int nSeason = getSeason(date);
        if (nSeason == 1) {
            c.set(Calendar.MONTH, Calendar.JANUARY);
            season[0] = c.getTime();
            c.set(Calendar.MONTH, Calendar.FEBRUARY);
            season[1] = c.getTime();
            c.set(Calendar.MONTH, Calendar.MARCH);
            season[2] = c.getTime();
        }else if (nSeason == 2) {
            c.set(Calendar.MONTH, Calendar.APRIL);
            season[0] = c.getTime();
            c.set(Calendar.MONTH, Calendar.MAY);
            season[1] = c.getTime();
            c.set(Calendar.MONTH, Calendar.JUNE);
            season[2] = c.getTime();
        }else if (nSeason == 3) {
            c.set(Calendar.MONTH, Calendar.JULY);
            season[0] = c.getTime();
            c.set(Calendar.MONTH, Calendar.AUGUST);
            season[1] = c.getTime();
            c.set(Calendar.MONTH, Calendar.SEPTEMBER);
            season[2] = c.getTime();
        }else if (nSeason == 4) {
            c.set(Calendar.MONTH, Calendar.OCTOBER);
            season[0] = c.getTime();
            c.set(Calendar.MONTH, Calendar.NOVEMBER);
            season[1] = c.getTime();
            c.set(Calendar.MONTH, Calendar.DECEMBER);
            season[2] = c.getTime();
        }
        return season;
    }
    public int getSeason(Date date) {
        int season = 0;
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int month = c.get(Calendar.MONTH);
        switch (month) {
            case Calendar.JANUARY:
            case Calendar.FEBRUARY:
            case Calendar.MARCH:
                season = 1;
                break;
            case Calendar.APRIL:
            case Calendar.MAY:
            case Calendar.JUNE:
                season = 2;
                break;
            case Calendar.JULY:
            case Calendar.AUGUST:
            case Calendar.SEPTEMBER:
                season = 3;
                break;
            case Calendar.OCTOBER:
            case Calendar.NOVEMBER:
            case Calendar.DECEMBER:
                season = 4;
                break;
            default:
                break;
        }
        return season;
    }

    private Object testPost(String param1, Object object) {
        String url = "http://47.94.148.26:8002/jx/";
        String urlData = "http://47.94.148.26:8002/jx/api/";
        try{
            URL path = new URL(url);
            // 获取token
            HttpURLConnection connection = (HttpURLConnection) path.openConnection();
            String token = connection.getHeaderField("Set-Cookie").substring(10,74);
            // 设置请求headers和cookies
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Type","multipart/form-data; charset=UTF-8");
            headers.add("X-CSRFToken",token);
            headers.add(HttpHeaders.COOKIE,"csrftoken="+token);
            headers.add(HttpHeaders.COOKIE,"payroll=apiuser");
            // 设置请求参数
            MultiValueMap<String,String> map = new LinkedMultiValueMap<>();
            map.add("csrfmiddlewaretoken",token);
            map.add("object",param1);
            map.add("id","all");

            HttpEntity<MultiValueMap<String, String>> formEntity = new HttpEntity<>(map,headers);
            ResponseEntity<Object> responseEntity = restTemplate.exchange(urlData, HttpMethod.POST, formEntity, Object.class);


            object = responseEntity.getBody();
        }catch (Exception e) {
            e.printStackTrace();
        }
        return object;
    }


    @ApiOperation("条件查询职工信息")
    @RequestMapping(value = "findEmployee",method = RequestMethod.GET)
    public Result findEmployee(@RequestParam(defaultValue = "1") Integer pageNum,
                               @RequestParam(defaultValue = "10")Integer pageSize,
                               String departmentId,
                               String teamGroupId,
                               String name){

        return ResultGenerator.genSuccessResult(employeeService.findEmployee(pageNum, pageSize, departmentId, teamGroupId, name));
    }

    @ApiOperation("修改职工班组和岗位类型")
    @RequestMapping(value = "updateEmployeeTeamAndPosition",method = RequestMethod.GET)
    public Result updateEmployeeTeamAndPosition(Integer employeeId,
                               String teamGroupName,
                               String positionType){

        if (employeeService.updateEmployeeTeamAndPosition(employeeId, teamGroupName, positionType) > 0)
            return ResultGenerator.genFailResult("修改成功");
        else

            return ResultGenerator.genFailResult("修改失败");
    }

    @ApiOperation("修改职工是否在岗45天")
    @RequestMapping(value = "updateEmployeeIs45Days",method = RequestMethod.GET)
    public Result updateEmployeeIs45Days(Integer employeeId,
                                         Boolean is45Days){

        if (employeeService.updateEmployeeIs45Days(employeeId, is45Days) > 0)
            return ResultGenerator.genFailResult("修改成功");
        else
            return ResultGenerator.genFailResult("修改失败");
    }

    /**
     * 2022/04/20
     * 班组和部分修改
     */
    @ApiOperation("查询班组信息及分主管的姓名")
    @GetMapping(value = "findTeamGroupAndName")
    public Result findTeamGroupAndName(String departmentId){
        return ResultGenerator.genSuccessResult(employeeService.findTeamGroupAndName(departmentId));
    }

    /**
     * 提醒：在班组表中记录分管和主管使用身份证号。
     * @param id
     * @param branchManagerIdCard
     * @param mainManagerIdCard
     * @return
     */
    @ApiOperation("修改班组的主管id，分管id")
    @GetMapping(value = "updateTeamGroupManagerId")
    public Result updateTeamGroupManagerId(Integer id,
                                           String branchManagerIdCard,
                                           String mainManagerIdCard){
        return ResultGenerator.genSuccessResult(employeeService.updateTeamGroupManagerId(id, branchManagerIdCard, mainManagerIdCard));
    }

    @ApiOperation("添加班组")
    @PostMapping(value = "addTeamGroup")
    public Result addTeamGroup(TeamGroup teamGroup){
        return ResultGenerator.genSuccessResult(employeeService.addTeamGroup(teamGroup));
    }

    @ApiOperation("查询所有部门，按星级从高到底排序")
    @GetMapping(value = "selectDepartmentOrder")
    public Result selectDepartmentOrder(){
        return ResultGenerator.genSuccessResult(departmentService.selectDepartmentOrder());
    }


}
